/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.androsz.electricsleepbeta.alarmclock;

import java.util.Calendar;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.androsz.electricsleepbeta.R;
import com.androsz.electricsleepbeta.app.SettingsActivity;

/**
 * Alarm Clock alarm alert: pops visible indicator and plays alarm tone. This
 * activity is the full screen version which shows over the lock screen with the
 * wallpaper as the background.
 */
public class AlarmAlertFullScreen extends Activity {

	// These defaults must match the values in res/xml/settings.xml
	private static final String DEFAULT_SNOOZE = "5";
	private static final String DEFAULT_VOLUME_BEHAVIOR = "2";
	protected static final String SCREEN_OFF = "screen_off";

	protected Alarm mAlarm;
	private int mVolumeBehavior;

	// Receives the ALARM_KILLED action from the AlarmKlaxon,
	// and also ALARM_SNOOZE_ACTION / ALARM_DISMISS_ACTION from other
	// applications
	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(final Context context, final Intent intent) {
			final String action = intent.getAction();
			if (action.equals(Alarms.ALARM_SNOOZE_ACTION)) {
				snooze();
			} else if (action.equals(Alarms.ALARM_DISMISS_ACTION)) {
				dismiss(false);
			} else if (action.equals(Alarms.ALARM_KILLED)) {
				final Alarm alarm = intent
						.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);
				if (alarm != null && mAlarm.id == alarm.id) {
					dismiss(true);
				}
			}
		}
	};

	// Dismiss the alarm.
	private void dismiss(final boolean killed) {
		Log.i(killed ? "Alarm killed" : "Alarm dismissed by user");
		// The service told us that the alarm has been killed, do not modify
		// the notification or stop the service.
		if (!killed) {
			// Cancel the notification and stop playing the alarm
			final NotificationManager nm = getNotificationManager();
			nm.cancel(mAlarm.id);
			stopService(new Intent(Alarms.ALARM_ALERT_ACTION));
			sendBroadcast(new Intent(Alarms.ALARM_DISMISSED_BY_USER_ACTION));
		}
		finish();
	}

	@Override
	public boolean dispatchKeyEvent(final KeyEvent event) {
		// Do this on key down to handle a few of the system keys.
		final boolean up = event.getAction() == KeyEvent.ACTION_UP;
		switch (event.getKeyCode()) {
		// Volume keys and camera keys dismiss the alarm
		case KeyEvent.KEYCODE_VOLUME_UP:
		case KeyEvent.KEYCODE_VOLUME_DOWN:
		case KeyEvent.KEYCODE_CAMERA:
		case KeyEvent.KEYCODE_FOCUS:
			if (up) {
				switch (mVolumeBehavior) {
				case 1:
					snooze();
					break;

				case 2:
					dismiss(false);
					break;

				default:
					break;
				}
			}
			return true;
		default:
			break;
		}
		return super.dispatchKeyEvent(event);
	}

	private NotificationManager getNotificationManager() {
		return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
	}

	@Override
	public void onBackPressed() {
		// Don't allow back to dismiss. This method is overriden by AlarmAlert
		// so that the dialog is dismissed.
		return;
	}

	@Override
	protected void onCreate(final Bundle icicle) {
		super.onCreate(icicle);

		mAlarm = getIntent().getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);

		// Get the volume/camera button behavior setting
		final String vol = getSharedPreferences(SettingsActivity.PREFERENCES, 0)
				.getString(SettingsActivity.KEY_VOLUME_BEHAVIOR,
						DEFAULT_VOLUME_BEHAVIOR);
		mVolumeBehavior = Integer.parseInt(vol);

		requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);

		final Window win = getWindow();
		win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
				| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
		// Turn on the screen unless we are being launched from the AlarmAlert
		// subclass.
		if (!getIntent().getBooleanExtra(SCREEN_OFF, false)) {
			win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
					| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
			/* | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON */);
		}

		updateLayout();

		// Register to get the alarm killed/snooze/dismiss intent.
		final IntentFilter filter = new IntentFilter(Alarms.ALARM_KILLED);
		filter.addAction(Alarms.ALARM_SNOOZE_ACTION);
		filter.addAction(Alarms.ALARM_DISMISS_ACTION);
		registerReceiver(mReceiver, filter);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (Log.LOGV) {
			Log.v("AlarmAlert.onDestroy()");
		}
		// No longer care about the alarm being killed.
		unregisterReceiver(mReceiver);
	}

	/**
	 * this is called when a second alarm is triggered while a previous alert
	 * window is still active.
	 */
	@Override
	protected void onNewIntent(final Intent intent) {
		super.onNewIntent(intent);

		if (Log.LOGV) {
			Log.v("AlarmAlert.OnNewIntent()");
		}

		mAlarm = intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);

		setTitle();
	}

	@Override
	protected void onResume() {
		super.onResume();
		// If the alarm was deleted at some point, disable snooze.
		if (Alarms.getAlarm(getContentResolver(), mAlarm.id) == null) {
			final Button snooze = (Button) findViewById(R.id.snooze);
			snooze.setEnabled(false);
		}
	}

	private void setTitle() {
		final String label = mAlarm.getLabelOrDefault(this);
		final TextView title = (TextView) findViewById(R.id.alertTitle);
		title.setText(label);
	}

	// Attempt to snooze this alert.
	private void snooze() {
		// Do not snooze if the snooze button is disabled.
		if (!findViewById(R.id.snooze).isEnabled()) {
			dismiss(false);
			return;
		}
		final String snooze = getSharedPreferences(
				SettingsActivity.PREFERENCES, 0).getString(
				SettingsActivity.KEY_ALARM_SNOOZE, DEFAULT_SNOOZE);
		final int snoozeMinutes = Integer.parseInt(snooze);

		final long snoozeTime = System.currentTimeMillis() + 1000 * 60
				* snoozeMinutes;
		Alarms.saveSnoozeAlert(AlarmAlertFullScreen.this, mAlarm.id, snoozeTime);

		// Get the display time for the snooze and update the notification.
		final Calendar c = Calendar.getInstance();
		c.setTimeInMillis(snoozeTime);

		// Append (snoozed) to the label.
		String label = mAlarm.getLabelOrDefault(this);
		label = getString(R.string.alarm_notify_snooze_label, label);

		// Notify the user that the alarm has been snoozed.
		final Intent cancelSnooze = new Intent(this, AlarmReceiver.class);
		cancelSnooze.setAction(Alarms.CANCEL_SNOOZE);
		cancelSnooze.putExtra(Alarms.ALARM_ID, mAlarm.id);
		final PendingIntent broadcast = PendingIntent.getBroadcast(this,
				mAlarm.id, cancelSnooze, 0);
		final NotificationManager nm = getNotificationManager();
		final Notification n = new Notification(R.drawable.stat_notify_alarm,
				label, 0);
		n.setLatestEventInfo(
				this,
				label,
				getString(R.string.alarm_notify_snooze_text,
						Alarms.formatTime(this, c)), broadcast);
		n.flags |= Notification.FLAG_AUTO_CANCEL
				| Notification.FLAG_ONGOING_EVENT;
		nm.notify(mAlarm.id, n);

		final String displayTime = getString(R.string.alarm_alert_snooze_set,
				snoozeMinutes);
		// Intentionally log the snooze time for debugging.
		Log.v(displayTime);

		// Display the snooze minutes in a toast.
		Toast.makeText(AlarmAlertFullScreen.this, displayTime,
				Toast.LENGTH_LONG).show();
		stopService(new Intent(Alarms.ALARM_ALERT_ACTION));
		finish();
	}

	private void updateLayout() {
		final LayoutInflater inflater = LayoutInflater.from(this);

		setContentView(inflater.inflate(R.layout.alarm_alert, null));

		/*
		 * snooze behavior: pop a snooze confirmation view, kick alarm manager.
		 */
		final Button snooze = (Button) findViewById(R.id.snooze);
		snooze.requestFocus();
		snooze.setOnClickListener(new Button.OnClickListener() {
			@Override
			public void onClick(final View v) {
				snooze();
			}
		});

		/* dismiss button: close notification */
		findViewById(R.id.dismiss).setOnClickListener(
				new Button.OnClickListener() {
					@Override
					public void onClick(final View v) {
						dismiss(false);
					}
				});

		/* Set the title from the passed in alarm */
		setTitle();
	}
}
